﻿using System;
using System.Collections.Generic;

using Moq;

using Sustainalytics.ClientDW.Entities;
using Sustainalytics.Companies;
using Sustainalytics.DataLayer.Shared;
using Sustainalytics.Entities;
using Sustainalytics.Portfolios.BL.Exceptions;
using Sustainalytics.Utils;

using Xunit;
using MongoDB.Driver;
using Sustainalytics.DataLayer.EsgRatings;
using Sustainalytics.Replication.Publisher;
using System.Configuration.Abstractions;

namespace Sustainalytics.Portfolios.BL.Tests.IntegrationTest
{
    public class CustomPortfolioUpdates
    {
        private readonly Mock<IScreeningToolFilterManager> _filterMock = new Mock<IScreeningToolFilterManager>();

        private readonly Mock<IRepositoryCollection<PortfolioDetails>> _portfolioDetailsRepositoryMock =
            new Mock<IRepositoryCollection<PortfolioDetails>>();

        private readonly Mock<IRepositoryCollection<PortfolioMatches>> _portfolioMatchesRepositoryMock =
         new Mock<IRepositoryCollection<PortfolioMatches>>();

        private readonly Mock<IEsgInputFileRepository> _esgInputFileRepositoryMock = new Mock<IEsgInputFileRepository>();

        private readonly Guid _portfolioGuid = Guid.NewGuid();

        private readonly Mock<IRepositoryCollection<Portfolio>> _portfolioRepositoryMock =
            new Mock<IRepositoryCollection<Portfolio>>();

        private readonly Mock<ISubscribeToPortfolioManagement> _subscriptionManagement =
            new Mock<ISubscribeToPortfolioManagement>();

        private readonly Mock<IRepositoryCollection<PortfolioUserInput>> _userInputRepositoryMock =
            new Mock<IRepositoryCollection<PortfolioUserInput>>();

        private ICustomPortfolioUpdateHandler Sut { get; set; }

        private readonly Dictionary<string, string> _serviceBusParams = new Dictionary<string, string>
            {
                { "ConnectionString", "Endpoint=sb://sust-test-ns.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=Dh/4Cq0qrOC7xOJFUYHLGJvQ6pqj4BuwjTS4HUjL6uQ=" },
                { "RegionEndpoint", "TT" },
                { "SessionId", "Portfolios" },
                { "TopicPath", "test-topic" },
            };

        public class CustomPortfolioAdd : CustomPortfolioUpdates
        {
            private readonly PortfolioUserClaims _anotherUser = new PortfolioUserClaims
            {
                UserName =
                                                                            "teodor.bajan@sustainalytics.com",
                UserFullName =
                                                                            "Teodor Bajan",
                UserId =
                                                                            new Guid(
                                                                            "4387c2a7-1eda-11e4-92ce-6c3be5be9f88"),
                AccountId =
                                                                            new Guid(
                                                                            "888ea769-2d17-e411-92ce-6c3be5be9f98")
            };

            private readonly PortfolioUserClaims _userClaimsFake = new PortfolioUserClaims
            {
                UserName =
                                                                               "teodor.bajan@sustainalytics.com",
                UserFullName =
                                                                               "Teodor Bajan",
                UserId =
                                                                               new Guid(
                                                                               "4387c2a7-1eda-11e4-92ce-6c3be5be9f88"),
                AccountId =
                                                                               new Guid(
                                                                               "528ea769-2d17-e411-92ce-6c3be5be9f98")
            };

            public CustomPortfolioAdd()
            {
                this.Sut = new CustomPortfolioUpdateHandler(this._portfolioRepositoryMock.Object, this._portfolioDetailsRepositoryMock.Object,
                    this._portfolioMatchesRepositoryMock.Object,
                    this._userInputRepositoryMock.Object,
                    this._esgInputFileRepositoryMock.Object, new ServiceBusPublisher(_serviceBusParams),
                    new CompanyMatchingLogic(MongoDB.Extensions.MongoFactory.GetCollectionFromDatabase<CorporateData>(ConfigurationManager.Instance.ConnectionStrings["ClientPlatform"].ConnectionString)));
                this.Sut.SetScreeningToolFilterManagement(this._filterMock.Object);
                this.Sut.SetSubscriptionManager(this._subscriptionManagement.Object);
            }

            [Theory]
            [InlineData(PortfolioSharingStatus.Private)]
            [InlineData(PortfolioSharingStatus.Shared)]
            public void When_Two_Users_SameName_Different_Account_Must_Create_Private_Portfolio_Same_Name(
                PortfolioSharingStatus status)
            {
                this.Sut.AddPortfolioAndDetails("test", status, new PortfolioSecuritiesRow[] { }, this._userClaimsFake);
                this.Sut.AddPortfolioAndDetails("test", status, new PortfolioSecuritiesRow[] { }, this._anotherUser);

                this._portfolioRepositoryMock.Verify(x => x.CreateOrUpdate(It.IsAny<Portfolio>()), times: Times.Exactly(2));
            }
        }

        public class CustomPortfolioAddCompany : CustomPortfolioUpdates
        {
            private readonly PortfolioUserClaims _userClaimsFake = new PortfolioUserClaims
            {
                UserName =
                                                                               "ileana.popescu@sustainalytics.com",
                UserFullName =
                                                                               "Ileana Popescu",
                UserId =
                                                                               new Guid(
                                                                               "4387c2a7-1eda-11e4-92ce-6c3be5be9f98"),
                AccountId =
                                                                               new Guid(
                                                                               "528ea769-2d17-e411-92ce-6c3be5be9f98")
            };

            private readonly Guid _portfolioId = new Guid("4387c2a7-1eda-11e4-92ce-6c3be5be9f99");
            private Mock<CorporateDataUniversesLoader> _corporateDataMock;

            public CustomPortfolioAddCompany()
            {
                var portfolio = PortfolioBuilder.Build(
                    this._portfolioId,
                    "test",
                    PortfolioSharingStatus.Private,
                    this._userClaimsFake);
                this._portfolioRepositoryMock.Setup(x => x.Read(It.IsAny<Guid>())).Returns(portfolio);
                this.Sut = new CustomPortfolioUpdateHandler(this._portfolioRepositoryMock.Object, this._portfolioDetailsRepositoryMock.Object,
                    this._portfolioMatchesRepositoryMock.Object,
                    this._userInputRepositoryMock.Object, 
                    this._esgInputFileRepositoryMock.Object,
                    new ServiceBusPublisher(_serviceBusParams),
                    new CompanyMatchingLogic(MongoDB.Extensions.MongoFactory.GetCollectionFromDatabase<CorporateData>(ConfigurationManager.Instance.ConnectionStrings["ClientPlatform"].ConnectionString)));
                this.Sut.SetPortfolioMatching(new PortfolioMatching(new CompanyMatchingLogic(MongoDB.Extensions.MongoFactory.GetCollectionFromDatabase<CorporateData>(ConfigurationManager.Instance.ConnectionStrings["ClientPlatform"].ConnectionString)), _corporateDataMock.Object));
            }
        }

        public class CustomPortfolioDelete : CustomPortfolioUpdates
        {
            private readonly PortfolioUserClaims _anotherUser = new PortfolioUserClaims
            {
                UserName =
                                                                            "teodor.bajan@sustainalytics.com",
                UserFullName =
                                                                            "Teodor Bajan",
                UserId =
                                                                            new Guid(
                                                                            "4387c2a7-1eda-11e4-92ce-6c3be5be9f88"),
                AccountId =
                                                                            new Guid(
                                                                            "528ea769-2d17-e411-92ce-6c3be5be9f98")
            };

            private readonly PortfolioUserClaims _userClaimsFake = new PortfolioUserClaims
            {
                UserName =
                                                                               "ileana.popescu@sustainalytics.com",
                UserFullName =
                                                                               "Ileana Popescu",
                UserId =
                                                                               new Guid(
                                                                               "4387c2a7-1eda-11e4-92ce-6c3be5be9f98"),
                AccountId =
                                                                               new Guid(
                                                                               "528ea769-2d17-e411-92ce-6c3be5be9f98")
            };
            
            [Fact]
            public void PortfolioManager_Delete_Security_NotAllowed_Throws_Exception()
            {
                // Arrange
                var portfolio = PortfolioBuilder.Build(
                    this._portfolioGuid,
                    "test",
                    PortfolioSharingStatus.Shared,
                    this._userClaimsFake);
                portfolio.CompanyCount = 1;
                portfolio.DateModified = DateTime.Today.AddDays(-2);
                var security = new PortfolioDetails()
                {
                    CompanyId = Guid.NewGuid(),
                    MatchedInfo = new MatchedInformation("1234", "company"),
                    PortfolioId = this._portfolioGuid,
                    DisplayInfo = new DisplayInformation("1234", "security 1"),
                    SecurityId = "1",
                    Id = Guid.NewGuid()
                };
                this.Sut = new CustomPortfolioUpdateHandler(this._portfolioRepositoryMock.Object,
                    this._portfolioDetailsRepositoryMock.Object,
                    this._portfolioMatchesRepositoryMock.Object,
                    this._userInputRepositoryMock.Object,
                    this._esgInputFileRepositoryMock.Object, new ServiceBusPublisher(_serviceBusParams),
                    new CompanyMatchingLogic(MongoDB.Extensions.MongoFactory.GetCollectionFromDatabase<CorporateData>(ConfigurationManager.Instance.ConnectionStrings["ClientPlatform"].ConnectionString)));
                this.Sut.SetScreeningToolFilterManagement(this._filterMock.Object);
                this.Sut.SetSubscriptionManager(this._subscriptionManagement.Object);
                this._portfolioRepositoryMock.Setup(x => x.Read(this._portfolioGuid)).Returns(portfolio);

                // Assert
                Assert.Throws<PortfolioDetailsDeleteUnauthorisedException>(
                    () => this.Sut.DeletePortfolioSecurity(this._portfolioGuid, security.Id, this._anotherUser));
            }
        }
    }
}